var URICodec = {
    valid: x => typeof(x) === 'string' && /^((%[A-F0-9]{2})|\w|[;,/?:@&=+$#_.!~*'()\-])*$/g.test(x),
    encode: x => x.replace(/.|[\n\r]/g, v => /\w|[;,/?:@&=+$#_.!~*'()\-]/.test(v) ? v : `%${ v.charCodeAt(0).toString(16).toUpperCase().padStart(2,'0')}`),
    decode: x => x.replace(/%([A-F0-9]{2})/g, (v, i) => /[;,/?:@&=+#$]/.test(c = String.fromCharCode(parseInt(i, 16))) ? v : c),
}
URICodec.encode.component = x => x.replace(/.|[\n\r]/g, v => /\w|[-_.!~*'()]/.test(v) ? v : `%${ v.charCodeAt(0).toString(16).toUpperCase().padStart(2,'0')}`);
URICodec.decode.component = x => x.replace(/%([A-F0-9]{2})/g, (v, i) => String.fromCharCode(parseInt(i, 16)));